
// ------------- GLOBAL VARS ----------------------
var map, startCenter, content;


(function ($) {
  
  /**
   * Initializes Map
   */
  function mapInit() {
    // Setting container for map
    var mapCanvas = $("#map_canvas")[0];
    
    // Creating an option object for the map  
    var mapOptions = {
      backgroundColor: '#000000',
      center: startCenter,
      zoom: 2,
      mapTypeControlOptions: {    
        // Removing all usual map types from list
        mapTypeIds: "demo"
      },
      mapTypeControl: false,      // Hiding the map type control
      streetViewControl: false,   // Hiding the StreetView control
      
      // Positioning the controls 
      panControlOptions: {
        position: google.maps.ControlPosition.LEFT_CENTER
      },
      zoomControlOptions: {
        position: google.maps.ControlPosition.LEFT_CENTER
      }     
    };
    
    // Initializing the map  
    map = new google.maps.Map(mapCanvas, mapOptions);
  }
  
  // --------------------- START IMAGEMAPTYPE ---------------------------------
  
  /**
   *  Initializes the ImageMapType
   */
  function mapTypeInit() {
    // Creating an option object for the ImageMapType
    var demoTypeOptions = {
      getTileUrl: mapTypeGetTileUrl,
      tileSize: new google.maps.Size(256, 256),
      isPng: true,
      maxZoom: 5,     // range of
      minZoom: 1,     // zoom levels
      name: "Demo"    // label for mapTypeControl if displayed
    };
    
    // Creating the ImageMapType object
    var demoMapType = new google.maps.ImageMapType(demoTypeOptions);
    // Adding "demo" to the mapTypes register
    map.mapTypes.set('demo', demoMapType);
    // Activating the "demo" MapType
    map.setMapTypeId('demo');
  }
  
  
  /**
   *  Builds url for background
   */
  function mapTypeGetTileUrl( coord, zoom ) {
    var backgroundPath = "img/bg";    // path to the background folder
    
    // Finding out if map is out of boundaries and if backgrounds should be repeated.
    // If not no background url is returned.
    var normalizedCoord = mapTypeGetNormalizedCoord(coord, zoom);
    if (!normalizedCoord) {
      return false;
    }
    
    // Calculating coordinates and return background url
    var bound = Math.pow(2, zoom);
    var xCoord = normalizedCoord.x;
    var yCoord = (bound - normalizedCoord.y - 1);
    return backgroundPath + "/" + zoom + "/" + xCoord + "/" + yCoord + ".png";
  }
  
  
  /**
   *  Normalizes the coords that tiles repeat across the x axis (horizontally)
   *  like the standard Google map tiles.
   */
  function mapTypeGetNormalizedCoord( coord, zoom ) {
    var y = coord.y;
    var x = coord.x;
  
    // tile range in one direction range is dependent on zoom level
    // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
    var tileRange = 1 << zoom;
    
    // don't repeat across y-axis
    if (y < 0 || y >= tileRange)
      return null;                                  
    
    // repeat across x-axis
    if (x < 0 || x >= tileRange)
      x = (x % tileRange + tileRange) % tileRange;  
  
    return { x: x, y: y };
  }
  
  // --------------------- IMAGEMAPTYPE END -----------------------------------
  
  
    // --------------------- START NAVIGATION -----------------------------------
  /**
   *  Integrates the header into Google Maps' control grid.
   *  Adds event listeners for click-event on links.
   */
  function navigationInit(){
    // Integrating the header into Google Maps' control grid
    var header = $("#header")[0];
    map.controls[google.maps.ControlPosition.TOP_CENTER].push(header);
    
    // Adding click event to links
    $("#navigation").find(" ul li a").each(function(i){
      $(this).click(function(event){
        event.preventDefault();
        
        // Getting index of the link
        var index = $("#navigation").find(" ul li a").index($(this));
        
        // Moving to startCenter if first element was clicked
        // else opening the InfoBox matching to index
        if (index == 0){
          map.setZoom(2);
          setTimeout(function(){ map.panTo(startCenter); }, 250);
        }
        else {
          // index of content starts at 0 but in navigation chapters start at 1
          map.setZoom(4);
          setTimeout(function(){ map.panTo(content[index-1].position); }, 250);
        }
        
        // Assign active status/class to the clicked link
        navigationHighlight(index);
      });      
    });
  }
  
  /**
   * Highlights the navigation element matching
   * the visible content chapter
   */
  function navigationHighlight(index){
    var links = $("#navigation").find(" ul li a");
    // Removing all highlights
    links.removeClass("active");
    // If index is negative no element gets highlighted
    if (index >= 0)
      links.eq(index).addClass("active");
  }
  
  // ---------------------- END NAVIGATION ------------------------------------
  
  // ------------------ START CONTENT OVERLAYS --------------------------------
  
  /**
   * Creates a clickable area on the background
   * and a InfoBox for each chapter of the content
   */
  function overlaysInit(){
    // Creating an options object for the marker images
    var mImgOptions = {
      width: new google.maps.Size(32, 32),  // This marker is 32 pixels wide & tall.
      origin: new google.maps.Point(0,0),   // The origin for this image is 0,0.
      anchor: new google.maps.Point(16, 16) // The anchor is the center of the circle 16,16.
    };
    for (var i = 0; i < content.length; i++){
      // Creating the marker images for normal and hover state
      content[i].mImage = new google.maps.MarkerImage("img/c"+i+".png",
        mImgOptions.width, mImgOptions.origin, mImgOptions.anchor);
      content[i].mHoverImage = new google.maps.MarkerImage("img/c"+i+"-hover.png",
        mImgOptions.width, mImgOptions.origin, mImgOptions.anchor);
      
      // Creating the actual marker
      // it appears as soon as it has a map defined
      content[i].marker = new google.maps.Marker({
        position: content[i].markerPos,
        icon: content[i].mImage,
        map: map,
        zIndex: i
      });
      
      // Adding hover and click events
      google.maps.event.addListener(content[i].marker, 'mouseover', overlaysMarkerHover);
      google.maps.event.addListener(content[i].marker, 'mouseout', overlaysMarkerHover);
      google.maps.event.addListener(content[i].marker, 'click', function(event){
        // Zooming out and center map
        map.setZoom(2);
        setTimeout(function(){ map.panTo(startCenter); }, 250);
      });
      
      // Creates transparent overlay
      content[i].overlay = new google.maps.GroundOverlay(
        null, content[i].overlayBounds, { map: map });
    }
  }
  
  /**
   *  Changes marker image on mouseover and mouseout
   */  
  function overlaysMarkerHover(event) {
    var index = this.getZIndex();
    var image = event.type == "mouseover" ?
      content[index].mHoverImage : content[index].mImage;
    this.setIcon(image);
  }
  
  
  // ------------------- END CONTENT OVERLAYS ---------------------------------
  

  $(document).ready(function() { 
    content = [
      {
        position: new google.maps.LatLng(-76, -116.5),
        markerPos: new google.maps.LatLng(-82.28, -117),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-77.967, -126.143),
          new google.maps.LatLng(-73.552, -107.993))
      },
      {
        position: new google.maps.LatLng(-54.5, -38.25),
        markerPos: new google.maps.LatLng(-54.5, -76.28),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-59.286, -47.656),
          new google.maps.LatLng(-48.717, -29.507))
      },
      {
        position: new google.maps.LatLng(-78.4, 19.3),
        markerPos: new google.maps.LatLng(-83.4, -0.95),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-80.034, 10),
          new google.maps.LatLng(-76.340, 28.193))
      },
      {
        position: new google.maps.LatLng(-47.9, 77.4),
        markerPos: new google.maps.LatLng(-20.17, 88.65),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-53.407, 68.096),
          new google.maps.LatLng(-41.208, 86.201))
      },
      {
        position: new google.maps.LatLng(-76.5, 126.6),
        markerPos: new google.maps.LatLng(-73.5, 161.94),
        overlayBounds: new google.maps.LatLngBounds(
          new google.maps.LatLng(-78.437, 116.875),
          new google.maps.LatLng(-74.187, 135.068))
      }
    ];
  
    // coordinates for center of the map (more or less)
    startCenter = new google.maps.LatLng(-60.864, -18.652);  
    mapInit();
    mapTypeInit();
    navigationInit();
    overlaysInit();
  });  
  
})(jQuery);